package net.obxlabs.tweetpad.behaviour;

import net.nexttext.*;
import net.nexttext.property.*;
import net.nexttext.behaviour.*;

/**
 * Shuffles a TextObject with one of its neighbours.
 */
public class Shuffle extends AbstractAction {
	public static final int OFFSET_X = 0;  // TODO consolidate this with Maker+Swap+ReorderSiblings
	
    private double changeRatio;
    
    /** 
     * Builds a default Shuffle.
     */
    public Shuffle() {
        this(.5);
    }
    
    /**
     * Builds a Shuffle.
     * 
     * @param changeRatio the change ratio
     */
    public Shuffle(double changeRatio) {
        this.changeRatio = changeRatio;
    }
    
    /**
     * Shuffles a TextObject with another at the same level.
     * <p>The input parameter cannot be a TextObjectRoot.</p>
     */
    public ActionResult behave(TextObject to) {
    	// don't do anything if the TextObject is a root (no parent)
    	if (to instanceof TextObjectRoot || to.getParent() == null) {
            return new ActionResult(true, true, false);
        }
    	
		TextObjectGroup parent = to.getParent();
		if (Math.random() < changeRatio) {
    		// get the swapped TextObject
    		int locTwo = (int)Math.floor(Math.random()*parent.getNumChildren())+1;
    		TextObject swapTo = parent.getLeftMostChild();
    		int count = 1;
    		while (count < locTwo) {
    			swapTo = swapTo.getRightSibling();
    			count++;
    		}
    		
    		// get the location of the first TextObject
    		int locOne = 1;
    		TextObject searchTo = parent.getLeftMostChild();
    		while (searchTo != to) {
    			searchTo = searchTo.getRightSibling();
    			locOne++;
    		}
    		
    		// swap the two TextObjects coordinates
    		if (swap(to, swapTo)) {
    			// replace everything nicely on the line
    			repositionChildren(parent);
    		}
    	}
    	
    	return new ActionResult(true, true, false);
    }
    
    public boolean swap(TextObject toOne, TextObject toTwo) {
    	if (toOne == toTwo) {
    		// same TextObject, there is nothing to do
    		return false;
    	}
    	
    	if (toOne.toString().compareTo(" ") == 0 || toTwo.toString().compareTo(" ") == 0) {
    		// one of the TextObjects is a space, there is nothing to do
    		return false;
    	}
    	
    	//System.out.println("Shuffle: Swapping '"+toOne+"' with '"+toTwo+"'");
    	Vector3Property posOne = getPosition(toOne);
    	Vector3Property posTwo = getPosition(toTwo);
    	Vector3Property tempPosOne = new Vector3Property(posOne.get().getLocation());
    	posOne.set(posTwo.get());
    	posTwo.set(tempPosOne.get());
    	
    	// swap the location properties
    	NumberProperty locOne = (NumberProperty)toOne.getProperty("ShuffleLocation");
    	NumberProperty locTwo = (NumberProperty)toTwo.getProperty("ShuffleLocation");
    	NumberProperty tempLocOne = new NumberProperty(locOne.get());
    	locOne.set(locTwo.get());
    	locTwo.set(tempLocOne.get());
    	
    	return true;
    }
    
    public void repositionChildren(TextObjectGroup tog) {
    	TextObject[] orderedChildren = new TextObject[tog.getNumChildren()];
    	
    	// create an ordered list of the children
    	for (TextObject child = tog.getLeftMostChild(); child != null; child = child.getRightSibling()) {
    		int loc = (int)((NumberProperty)child.getProperty("ShuffleLocation")).get();
    		orderedChildren[loc-1] = child;
    	}
    	
    	// move every child where he belongs on the line
    	double currX = 0;
    	double y = orderedChildren[0].getPosition().get().y;
    	for (int i=0; i < orderedChildren.length; i++) {
    		orderedChildren[i].getPosition().set(new Vector3(currX, y));
    		currX += orderedChildren[i].getBounds().width+OFFSET_X;
    	}
    }
}
